package com.yzcrm.erp.kms.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.yzcrm.common.config.paragetter.BasePageRequest;
import com.yzcrm.common.constant.BaseConstant;
import com.yzcrm.common.lucene.LuceneIndex;
import com.yzcrm.erp.admin.entity.AdminField;
import com.yzcrm.erp.admin.entity.AdminScene;
import com.yzcrm.erp.admin.service.AdminFieldService;
import com.yzcrm.erp.admin.service.AdminSceneService;
import com.yzcrm.erp.admin.service.AdminUserService;
import com.yzcrm.erp.crm.common.CrmEnum;
import com.yzcrm.erp.crm.service.CrmRecordService;
import com.yzcrm.erp.kms.common.KmsEnum;
import com.yzcrm.erp.kms.entity.KmsFile;
import com.yzcrm.utils.AuthUtil;
import com.yzcrm.utils.BaseUtil;
import com.yzcrm.utils.ParamsUtil;
import com.yzcrm.utils.R;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexOptions;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiang.xue
 */
public class KmsFileService {

    @Inject
    private CrmRecordService crmRecordService;

    @Inject
    private AdminFieldService adminFieldService;

    @Inject
    private AdminSceneService adminSceneService;

    @Inject
    private LuceneIndex luceneIndex;

    /**
     * 追加知识库文件
     * @param jsonObject
     * @return
     */
    @Before(Tx.class)
    public R addOrUpdate(JSONObject jsonObject) {

//        Log.getLog(KmsFileService.class).info(jsonObject.toString() + "....");

        KmsFile kmsFile = jsonObject.getObject("entity", KmsFile.class);
        if(ObjectUtil.isNull(kmsFile)) {
            R.error("参数不正确");
        }
//        Log.getLog(KmsFileService.class).info(kmsFile + "....");

        // 获取文件扩展名
        String extension = "";
        if(ObjectUtil.isNotEmpty(kmsFile.getPath())) {
            int index = kmsFile.getPath().lastIndexOf(".");
            if (index != -1) {
                extension = kmsFile.getPath().substring(index + 1);
            }
        }

        String batchId = StrUtil.isNotEmpty(kmsFile.getBatchId()) ? kmsFile.getBatchId() : IdUtil.simpleUUID();
        if(kmsFile.getFileId() != null){
            crmRecordService.updateRecord(jsonObject.getJSONArray("field"), batchId);
        }
        adminFieldService.save(jsonObject.getJSONArray("field"), batchId);
        boolean flag;
        if(kmsFile.getFileId() != null){

            kmsFile.setFileType(extension);
            // 知识库文件暂时不用审核
            kmsFile.setCheckStatus(1);
            KmsFile oldKmsFile = new KmsFile().dao().findById(kmsFile.getFileId());
            crmRecordService.updateRecord(oldKmsFile, kmsFile, CrmEnum.KMS_FILE);
            kmsFile.setUpdateTime(DateUtil.date());
            kmsFile.setUpdateUserId(BaseUtil.getUser().getUserId());
            flag = kmsFile.update();

            // 更新索引
            luceneIndex.updateContent(BaseConstant.LUCENE_PATH_FILE, CrmEnum.KMS_FILE.getType()+"", kmsFile.getFileId().toString(), kmsFile.getTitle(), kmsFile.getContent());

        }else{

            kmsFile.setFileType(extension);
            kmsFile.setCreateTime(DateUtil.date());
            kmsFile.setUpdateTime(DateUtil.date());
            kmsFile.setCreateUserId(BaseUtil.getUser().getUserId());
            kmsFile.setBatchId(batchId);
            kmsFile.setCheckStatus(1);// 知识库文件暂时不用审核
            kmsFile.setStatus(1);
            kmsFile.setOwnerUserId(BaseUtil.getUser().getUserId());

            flag = kmsFile.save();
            crmRecordService.addRecord(kmsFile.getFileId().intValue(), CrmEnum.KMS_FILE);

            // 创建索引
            luceneIndex.addContent(BaseConstant.LUCENE_PATH_FILE, CrmEnum.KMS_FILE.getType()+"", kmsFile.getFileId().toString(), kmsFile.getTitle(), kmsFile.getContent());
        }

        return flag ? R.ok().put("data", Kv.by("file_id", kmsFile.getFileId()).set("title", kmsFile.getTitle())) : R.error();
    }

    /**
     * 获取场景 并 获取知识库文件列表
     * @param basePageRequest
     * @return
     */
    public R filterConditionAndGetPageList(BasePageRequest basePageRequest){

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Integer sceneId = jsonObject.getInteger("sceneId");
        JSONObject data = new JSONObject();
        if(sceneId != null && sceneId != 0){
            data = JSON.parseObject(AdminScene.dao.findById(sceneId).getData());
        }
        if(sceneId == null && jsonObject.getInteger("type") == 1){
            data = new JSONObject().fluentPut("is_transform", new JSONObject().fluentPut("name", "is_transform").fluentPut("condition", "is").fluentPut("value", "0"));
        }
        if(jsonObject.getJSONObject("data") != null){
            if(data != null){
                data.putAll(jsonObject.getJSONObject("data"));
            }
        }
        jsonObject.put("data",data);
        basePageRequest.setJsonObject(jsonObject);
        return getFilePageList(basePageRequest);
    }

    /**
     * 获取知识库文件列表
     * @param basePageRequest
     * @return
     */
    public R getFilePageList(BasePageRequest basePageRequest) {

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Kv kv = new Kv();
        List<JSONObject> queryList = new ArrayList<>();
        Integer type = jsonObject.getInteger("type");
        boolean isValid = jsonObject.getBoolean("isValid") != null ? jsonObject.getBoolean("isValid") : false;

        //自定义字段列表
        Map<String, AdminField> fieldMap = adminSceneService.getAdminFieldMap(type);

        // 取得场景名称 同label
        String realm = CrmEnum.parse(type).getName();
        if(ObjectUtil.isNull(realm)) {
            return R.error("type不符合要求");
        }

        // 附加检索条件
        JSONObject data = basePageRequest.getJsonObject().getJSONObject("data");
        if (!adminSceneService.appendSqlCondition(kv, fieldMap, queryList, data, type)){
            return R.error("参数包含非法字段");
        }
        String search = basePageRequest.getJsonObject().getString("search");
        if(StrUtil.isNotEmpty(search)){
            if (!adminSceneService.appendSqlSearch(type, queryList, search)){
                return R.error("参数包含非法字段");
            }
            if(!kv.containsKey("fixed")){
                kv.set("fixed",true);
            }
        }

        // 获取排序字段
        String camelField = basePageRequest.getJsonObject().getString("sortField");
        String sortField = StrUtil.toUnderlineCase(camelField);
        String orderNum = basePageRequest.getJsonObject().getString("order");
        if(StrUtil.isEmpty(sortField) || StrUtil.isEmpty(orderNum)){
            kv.set("orderByKey", "update_time").set("orderByType", "desc").set("fieldType", 1);
        }else{
            if(! ParamsUtil.isValid(sortField)){
                return R.error("参数包含非法字段");
            }
            orderNum = "2".equals(orderNum) ? "asc" : "desc";
            kv.set("orderByKey", sortField).set("orderByType", orderNum).set("fieldType", fieldMap.get(sortField) != null ? fieldMap.get(sortField).getFieldType() : 0);
        }

        // 开始生成条件SQL
        StringBuilder conditions = new StringBuilder();

        //获取已审核数据
        if(isValid) {
            conditions.append(" and check_status = 1");
        }

        conditions.append(" and status != 2");

        // 检索权限
        Long userId = BaseUtil.getUserId();
        List<Integer> roles = BaseUtil.getUser().getRoles();
        if(! BaseConstant.SUPER_ADMIN_USER_ID.equals(userId) && !roles.contains(BaseConstant.SUPER_ADMIN_ROLE_ID)){

            String menuRealm = "file";

            List<Long> longs = Aop.get(AdminUserService.class).queryUserByAuth(userId, menuRealm);
            if(longs != null && longs.size() > 0){
                conditions.append(" and (a.owner_user_id in (").append(StrUtil.join(",", longs)).append(")");
                conditions.append(")");
            }
        }
        JSONObject sqlObject = new JSONObject();
        sqlObject.put("sql", conditions.toString());
        sqlObject.put("type", 1);
        if(!kv.containsKey("fixed")){
            kv.set("fixed",true);
        }
        queryList.add(sqlObject);

        // 设置分页
        if(StrUtil.isEmpty(basePageRequest.getJsonObject().getString("excel"))){
            kv.set("page", (basePageRequest.getPage() - 1) * basePageRequest.getLimit()).set("limit", basePageRequest.getLimit());
        }

        String selectSql = "select * ";
        List<String> batchList = adminSceneService.queryBatchId(queryList);
        if(batchList.size()==0&&kv.containsKey("field")){
            batchList.add("");
        }
        kv.set("select", selectSql).set("queryList", queryList).set("realm", realm).set("fieldMap", fieldMap).set("label", type);
        kv.set("batchList",batchList);
        SqlPara sqlPara = null;
        if(kv.getInt("fieldType") == 0){
            sqlPara = Db.getSqlPara("kms.file.queryFilePageList2", kv);
        }else{
            sqlPara = Db.getSqlPara("kms.file.queryFilePageList1", kv);
        }

        // 检索数据
        List<Record> recordPage = Db.find(sqlPara);

        JSONObject resultJsonObject = new JSONObject();
        resultJsonObject.put("list", recordPage);
        SqlPara countSql = Db.getSqlPara("kms.file.queryFilePageListCount", kv);
        Integer count = Db.queryInt(countSql.getSql(), countSql.getPara());
        resultJsonObject.put("totalRow", count);
        return R.ok().put("data", resultJsonObject);

    }

    /**
     * 根据知识库文件id查询
     */
    public Record queryById(Integer fileId){
        Record record = Db.findFirst(Db.getSql("kms.file.queryById"), fileId);
        List<Record> recordList = Db.find("select name,value from `yzcrm_admin_fieldv` where batch_id = ?", record.getStr("batch_id"));
        recordList.forEach(field -> record.set(field.getStr("name"), field.getStr("value")));
        return record;
    }

    /**
     * 查询编辑字段
     */
    public List<Record> queryField(Integer fileId){
        Record file = queryById(fileId);
        List<Record> fieldList = adminFieldService.queryUpdateField(CrmEnum.KMS_FILE.getType(), file);
        return fieldList;
    }

    /**
     * 根据id删除知识库文件
     */
    public R deleteByIds(String fileIds){
        String[] idsArr = fileIds.split(",");
        List<Record> idsList = new ArrayList<>();
        for(String id : idsArr){
            String permissions = "kms:file:delete";
            if(!BaseUtil.getUserId().equals(BaseConstant.SUPER_ADMIN_USER_ID) && !BaseUtil.getUser().getRoles().contains(BaseConstant.SUPER_ADMIN_ROLE_ID)
                    && !AuthUtil.isHavaAuth(permissions)
                    && Db.queryInt(Db.getSql("kms.file.queryIsOwnerUser"), BaseUtil.getUserId(), id) <= 0){
                return R.error("没有权限");
            }
            Record record = new Record();
            idsList.add(record.set("id", Integer.valueOf(id)));
        }

        List<Record> batchIdList = Db.find(Db.getSqlPara("kms.file.queryBatchIdByIds", Kv.by("ids", idsArr)));
        boolean result = Db.tx(() -> {
            Db.batch(Db.getSql("kms.file.deleteByIds"), "id", idsList, 100);
//            Db.batch("delete from yzcrm_admin_fieldv where batch_id = ?", "batch_id", batchIdList, 100);
            return true;
        });

        if(result == true) {

            for(String id : idsArr) {
                // 删除索引
                luceneIndex.deleteContent(BaseConstant.LUCENE_PATH_FILE, id);
            }
        }

        return result ? R.ok() : R.error();
    }

    /**
     * 基本信息
     */
    public List<Record> information(Integer customerId) {
        Record record = queryById(customerId);
        List<String> keyList = Arrays.asList("title", "content", "path", "standard_study_seconds", "size");
        List<Record> recordList = adminFieldService.queryInformation(CrmEnum.KMS_FILE, record, keyList);
        return recordList.stream().sorted(Comparator.comparingInt(r->-r.getInt("field_type"))).map(r-> r.remove("field_type","field_name","setting","type")).collect(Collectors.toList());
    }

}
